package ar.edu.unq.persistencia;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import ar.edu.unq.persistencia.commands.Command;

/**
 * TODO: description
 */
public class HibernateManager {

    private static HibernateManager inst = new HibernateManager();

    private ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<Session>();

    public Session getSession() {
        return this.sessionThreadLocal.get();
    }

    private SessionFactory sessionFactory;

    public static HibernateManager instance() {
        return inst;
    }

    public HibernateManager() {
        Configuration cfg = new Configuration();
        cfg.configure();
        this.sessionFactory = cfg.buildSessionFactory();
    }

    public void runInSession(final Command cmd) {
        Session session = this.sessionFactory.openSession();
        this.sessionThreadLocal.set(session);
        Transaction trans = session.beginTransaction();

        try {
            cmd.setSession(session);
            cmd.run();
            session.flush();
            trans.commit();
        } catch (Exception e) {
            trans.rollback();
            throw new RuntimeException(e);
        } finally {
            session.close();
            this.sessionThreadLocal.set(null);
        }

    }

    public void runInSessionWithOutTx(final Command cmd) {
        Session session = this.sessionFactory.openSession();
        this.sessionThreadLocal.set(session);
        try {
            cmd.setSession(session);
            cmd.run();
            session.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            session.close();
            this.sessionThreadLocal.set(null);
        }
    }

}
